{
 "cells": [
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T12:13:06.508206Z",
     "start_time": "2025-01-20T12:12:48.586694Z"
    }
   },
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "import time\n",
    "from tqdm.auto import tqdm\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, torch:\n",
    "    print(module.__name__, module.__version__)\n",
    "    \n",
    "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
    "print(device)\n",
    "\n",
    "seed = 42\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sys.version_info(major=3, minor=12, micro=3, releaselevel='final', serial=0)\n",
      "matplotlib 3.10.0\n",
      "numpy 1.26.4\n",
      "pandas 2.2.3\n",
      "sklearn 1.6.0\n",
      "torch 2.5.1+cpu\n",
      "cpu\n"
     ]
    }
   ],
   "execution_count": 1
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数据准备"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T12:13:09.547385Z",
     "start_time": "2025-01-20T12:13:06.510234Z"
    }
   },
   "source": [
    "from torchvision import datasets\n",
    "from torchvision.transforms import ToTensor\n",
    "from torch.utils.data import random_split\n",
    "\n",
    "# fashion_mnist图像分类数据集\n",
    "train_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=True,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")\n",
    "\n",
    "test_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=False,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")\n",
    "\n",
    "# torchvision 数据集里没有提供训练集和验证集的划分\n",
    "# 这里用 random_split 按照 11 : 1 的比例来划分数据集\n",
    "train_ds, val_ds = random_split(train_ds, [55000, 5000], torch.Generator().manual_seed(seed))"
   ],
   "outputs": [],
   "execution_count": 2
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T12:13:09.554756Z",
     "start_time": "2025-01-20T12:13:09.548396Z"
    }
   },
   "source": [
    "from torchvision.transforms import Normalize\n",
    "\n",
    "# 遍历train_ds得到每张图片，计算每个通道的均值和方差\n",
    "def cal_mean_std(ds):\n",
    "    mean = 0.\n",
    "    std = 0.\n",
    "    for img, _ in ds:\n",
    "        mean += img.mean(dim=(1, 2))\n",
    "        std += img.std(dim=(1, 2))\n",
    "    mean /= len(ds)\n",
    "    std /= len(ds)\n",
    "    return mean, std\n",
    "\n",
    "\n",
    "# print(cal_mean_std(train_ds))\n",
    "# 0.2860， 0.3205\n",
    "transforms = nn.Sequential(\n",
    "    Normalize([0.2856], [0.3202])\n",
    ")"
   ],
   "outputs": [],
   "execution_count": 3
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T12:13:09.562752Z",
     "start_time": "2025-01-20T12:13:09.555762Z"
    }
   },
   "source": [
    "from torch.utils.data.dataloader import DataLoader\n",
    "\n",
    "batch_size = 32\n",
    "# 从数据集到dataloader\n",
    "train_loader = DataLoader(train_ds, batch_size=batch_size, shuffle=True, num_workers=4)\n",
    "val_loader = DataLoader(val_ds, batch_size=batch_size, shuffle=False, num_workers=4)\n",
    "test_loader = DataLoader(test_ds, batch_size=batch_size, shuffle=False, num_workers=4)"
   ],
   "outputs": [],
   "execution_count": 4
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义模型\n",
    "\n",
    "使用深度可分离的卷积\n",
    "\n",
    "pytorch需要自行实现"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T12:13:09.573493Z",
     "start_time": "2025-01-20T12:13:09.565758Z"
    }
   },
   "source": [
    "# 自定义深度可分离卷积层，torch没有实现，tf有实现\n",
    "class DepthWiseConv2d(nn.Module):\n",
    "    def __init__(self, in_channels, out_channels, kernel_size, stride=1, padding=0, bias=True):\n",
    "        super(DepthWiseConv2d, self).__init__() #这里写为super().__init__()，等价的\n",
    "        self.depthwise_conv = nn.Conv2d(in_channels, in_channels, kernel_size, stride, padding, groups=in_channels, bias=False) #groups参数表示一个卷积核的每个通道分别进行运算\n",
    "        self.pointwise_conv = nn.Conv2d(in_channels, out_channels, 1, 1, 0, bias=bias)\n",
    "    \n",
    "    def forward(self, x):\n",
    "        x = self.depthwise_conv(x)\n",
    "        x = self.pointwise_conv(x)\n",
    "        return x"
   ],
   "outputs": [],
   "execution_count": 5
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T12:13:09.597958Z",
     "start_time": "2025-01-20T12:13:09.575498Z"
    }
   },
   "source": [
    "\n",
    "class CNN(nn.Module):\n",
    "    def __init__(self, activation=\"relu\"):\n",
    "        super(CNN, self).__init__()\n",
    "        self.activation = F.relu if activation == \"relu\" else F.selu\n",
    "        #第一次因为通道只有一个，为了保留更多特征，第一次进行一次卷积\n",
    "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, padding=\"same\")\n",
    "        self.conv2 = DepthWiseConv2d(in_channels=32, out_channels=32, kernel_size=3, padding=\"same\")\n",
    "        self.pool = nn.MaxPool2d(2, 2)\n",
    "        self.conv3 = DepthWiseConv2d(in_channels=32, out_channels=64, kernel_size=3, padding=\"same\")\n",
    "        self.conv4 = DepthWiseConv2d(in_channels=64, out_channels=64, kernel_size=3, padding=\"same\")\n",
    "        self.conv5 = DepthWiseConv2d(in_channels=64, out_channels=128, kernel_size=3, padding=\"same\")\n",
    "        self.conv6 = DepthWiseConv2d(in_channels=128, out_channels=128, kernel_size=3, padding=\"same\")\n",
    "        self.flatten = nn.Flatten()\n",
    "        # input shape is (28, 28, 1) so the fc1 layer in_features is 128 * 3 * 3\n",
    "        self.fc1 = nn.Linear(128 * 3 * 3, 128)\n",
    "        self.fc2 = nn.Linear(128, 10)\n",
    "        \n",
    "        self.init_weights()\n",
    "        \n",
    "    def init_weights(self):\n",
    "        \"\"\"使用 xavier 均匀分布来初始化全连接层、卷积层的权重 W\"\"\"\n",
    "        for m in self.modules():\n",
    "            if isinstance(m, (nn.Linear, nn.Conv2d)):\n",
    "                nn.init.xavier_uniform_(m.weight)\n",
    "                if m.bias is not None:\n",
    "                    nn.init.zeros_(m.bias)\n",
    "        \n",
    "    def forward(self, x):\n",
    "        act = self.activation\n",
    "        #x -->(batch_size, 1, 28, 28)\n",
    "        x = self.pool(act(self.conv2(act(self.conv1(x)))))  # (batch_size, 32, 14, 14)\n",
    "        x = self.pool(act(self.conv4(act(self.conv3(x)))))  # (batch_size, 64, 7, 7)\n",
    "        x = self.pool(act(self.conv6(act(self.conv5(x)))))  # (batch_size, 128, 3, 3)\n",
    "        x = self.flatten(x) # (batch_size, 128 * 3 * 3)\n",
    "        x = act(self.fc1(x)) # (batch_size, 128)\n",
    "        x = self.fc2(x) # (batch_size, 10)\n",
    "        return x\n",
    "    \n",
    "\n",
    "for idx, (key, value) in enumerate(CNN().named_parameters()):\n",
    "    print(f\"{key}\\tparamerters num: {np.prod(value.shape)}\")\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "conv1.weight\tparamerters num: 288\n",
      "conv1.bias\tparamerters num: 32\n",
      "conv2.depthwise_conv.weight\tparamerters num: 288\n",
      "conv2.pointwise_conv.weight\tparamerters num: 1024\n",
      "conv2.pointwise_conv.bias\tparamerters num: 32\n",
      "conv3.depthwise_conv.weight\tparamerters num: 288\n",
      "conv3.pointwise_conv.weight\tparamerters num: 2048\n",
      "conv3.pointwise_conv.bias\tparamerters num: 64\n",
      "conv4.depthwise_conv.weight\tparamerters num: 576\n",
      "conv4.pointwise_conv.weight\tparamerters num: 4096\n",
      "conv4.pointwise_conv.bias\tparamerters num: 64\n",
      "conv5.depthwise_conv.weight\tparamerters num: 576\n",
      "conv5.pointwise_conv.weight\tparamerters num: 8192\n",
      "conv5.pointwise_conv.bias\tparamerters num: 128\n",
      "conv6.depthwise_conv.weight\tparamerters num: 1152\n",
      "conv6.pointwise_conv.weight\tparamerters num: 16384\n",
      "conv6.pointwise_conv.bias\tparamerters num: 128\n",
      "fc1.weight\tparamerters num: 147456\n",
      "fc1.bias\tparamerters num: 128\n",
      "fc2.weight\tparamerters num: 1280\n",
      "fc2.bias\tparamerters num: 10\n"
     ]
    }
   ],
   "execution_count": 6
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T12:13:09.614013Z",
     "start_time": "2025-01-20T12:13:09.598965Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def count_parameters(model): #计算模型总参数量\n",
    "    return sum(p.numel() for p in model.parameters() if p.requires_grad)\n",
    "count_parameters(CNN())"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "184234"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 7
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T12:13:09.624542Z",
     "start_time": "2025-01-20T12:13:09.616020Z"
    }
   },
   "cell_type": "code",
   "source": "288 + 288 +288+ 1024 + 2048 + 576 +576+ 4096+ 8192 + 1152 + 16384 + 147456 + 1280",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "183648"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 8
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T12:13:09.632050Z",
     "start_time": "2025-01-20T12:13:09.626552Z"
    }
   },
   "cell_type": "code",
   "source": "32 + 32 + 64 + 64 + 128 + 128 +128+ 10",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "586"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 9
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T12:13:09.640373Z",
     "start_time": "2025-01-20T12:13:09.633070Z"
    }
   },
   "cell_type": "code",
   "source": "183648+586",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "184234"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 10
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练\n",
    "\n",
    "pytorch的训练需要自行实现，包括\n",
    "1. 定义损失函数\n",
    "2. 定义优化器\n",
    "3. 定义训练步\n",
    "4. 训练"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T12:13:10.719723Z",
     "start_time": "2025-01-20T12:13:09.641886Z"
    }
   },
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "@torch.no_grad()\n",
    "def evaluating(model, dataloader, loss_fct):\n",
    "    loss_list = []\n",
    "    pred_list = []\n",
    "    label_list = []\n",
    "    for datas, labels in dataloader:\n",
    "        datas = datas.to(device)\n",
    "        labels = labels.to(device)\n",
    "        # 前向计算\n",
    "        logits = model(datas)\n",
    "        loss = loss_fct(logits, labels)         # 验证集损失\n",
    "        loss_list.append(loss.item())\n",
    "        \n",
    "        preds = logits.argmax(axis=-1)    # 验证集预测\n",
    "        pred_list.extend(preds.cpu().numpy().tolist())\n",
    "        label_list.extend(labels.cpu().numpy().tolist())\n",
    "        \n",
    "    acc = accuracy_score(label_list, pred_list)\n",
    "    return np.mean(loss_list), acc\n"
   ],
   "outputs": [],
   "execution_count": 11
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### TensorBoard 可视化\n",
    "\n",
    "\n",
    "训练过程中可以使用如下命令启动tensorboard服务。\n",
    "\n",
    "```shell\n",
    "tensorboard \\\n",
    "    --logdir=runs \\     # log 存放路径\n",
    "    --host 0.0.0.0 \\    # ip\n",
    "    --port 8848         # 端口\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T12:13:28.956407Z",
     "start_time": "2025-01-20T12:13:10.721727Z"
    }
   },
   "source": [
    "from torch.utils.tensorboard import SummaryWriter\n",
    "\n",
    "\n",
    "class TensorBoardCallback:\n",
    "    def __init__(self, log_dir, flush_secs=10):\n",
    "        \"\"\"\n",
    "        Args:\n",
    "            log_dir (str): dir to write log.\n",
    "            flush_secs (int, optional): write to dsk each flush_secs seconds. Defaults to 10.\n",
    "        \"\"\"\n",
    "        self.writer = SummaryWriter(log_dir=log_dir, flush_secs=flush_secs)\n",
    "\n",
    "    def draw_model(self, model, input_shape):\n",
    "        self.writer.add_graph(model, input_to_model=torch.randn(input_shape))\n",
    "        \n",
    "    def add_loss_scalars(self, step, loss, val_loss):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/loss\", \n",
    "            tag_scalar_dict={\"loss\": loss, \"val_loss\": val_loss},\n",
    "            global_step=step,\n",
    "            )\n",
    "        \n",
    "    def add_acc_scalars(self, step, acc, val_acc):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/accuracy\",\n",
    "            tag_scalar_dict={\"accuracy\": acc, \"val_accuracy\": val_acc},\n",
    "            global_step=step,\n",
    "        )\n",
    "        \n",
    "    def add_lr_scalars(self, step, learning_rate):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/learning_rate\",\n",
    "            tag_scalar_dict={\"learning_rate\": learning_rate},\n",
    "            global_step=step,\n",
    "            \n",
    "        )\n",
    "    \n",
    "    def __call__(self, step, **kwargs):\n",
    "        # add loss\n",
    "        loss = kwargs.pop(\"loss\", None)\n",
    "        val_loss = kwargs.pop(\"val_loss\", None)\n",
    "        if loss is not None and val_loss is not None:\n",
    "            self.add_loss_scalars(step, loss, val_loss)\n",
    "        # add acc\n",
    "        acc = kwargs.pop(\"acc\", None)\n",
    "        val_acc = kwargs.pop(\"val_acc\", None)\n",
    "        if acc is not None and val_acc is not None:\n",
    "            self.add_acc_scalars(step, acc, val_acc)\n",
    "        # add lr\n",
    "        learning_rate = kwargs.pop(\"lr\", None)\n",
    "        if learning_rate is not None:\n",
    "            self.add_lr_scalars(step, learning_rate)\n"
   ],
   "outputs": [],
   "execution_count": 12
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save Best\n"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T12:13:28.966913Z",
     "start_time": "2025-01-20T12:13:28.958416Z"
    }
   },
   "source": [
    "class SaveCheckpointsCallback:\n",
    "    def __init__(self, save_dir, save_step=5000, save_best_only=True):\n",
    "        \"\"\"\n",
    "        Save checkpoints each save_epoch epoch. \n",
    "        We save checkpoint by epoch in this implementation.\n",
    "        Usually, training scripts with pytorch evaluating model and save checkpoint by step.\n",
    "\n",
    "        Args:\n",
    "            save_dir (str): dir to save checkpoint\n",
    "            save_epoch (int, optional): the frequency to save checkpoint. Defaults to 1.\n",
    "            save_best_only (bool, optional): If True, only save the best model or save each model at every epoch.\n",
    "        \"\"\"\n",
    "        self.save_dir = save_dir\n",
    "        self.save_step = save_step\n",
    "        self.save_best_only = save_best_only\n",
    "        self.best_metrics = -1\n",
    "        \n",
    "        # mkdir\n",
    "        if not os.path.exists(self.save_dir):\n",
    "            os.mkdir(self.save_dir)\n",
    "        \n",
    "    def __call__(self, step, state_dict, metric=None):\n",
    "        if step % self.save_step > 0:\n",
    "            return\n",
    "        \n",
    "        if self.save_best_only:\n",
    "            assert metric is not None\n",
    "            if metric >= self.best_metrics:\n",
    "                # save checkpoints\n",
    "                torch.save(state_dict, os.path.join(self.save_dir, \"best.ckpt\"))\n",
    "                # update best metrics\n",
    "                self.best_metrics = metric\n",
    "        else:\n",
    "            torch.save(state_dict, os.path.join(self.save_dir, f\"{step}.ckpt\"))\n",
    "\n"
   ],
   "outputs": [],
   "execution_count": 13
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Early Stop"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T12:13:28.977425Z",
     "start_time": "2025-01-20T12:13:28.970915Z"
    }
   },
   "source": [
    "class EarlyStopCallback:\n",
    "    def __init__(self, patience=5, min_delta=0.01):\n",
    "        \"\"\"\n",
    "\n",
    "        Args:\n",
    "            patience (int, optional): Number of epochs with no improvement after which training will be stopped.. Defaults to 5.\n",
    "            min_delta (float, optional): Minimum change in the monitored quantity to qualify as an improvement, i.e. an absolute \n",
    "                change of less than min_delta, will count as no improvement. Defaults to 0.01.\n",
    "        \"\"\"\n",
    "        self.patience = patience\n",
    "        self.min_delta = min_delta\n",
    "        self.best_metric = -1\n",
    "        self.counter = 0\n",
    "        \n",
    "    def __call__(self, metric):\n",
    "        if metric >= self.best_metric + self.min_delta:\n",
    "            # update best metric\n",
    "            self.best_metric = metric\n",
    "            # reset counter \n",
    "            self.counter = 0\n",
    "        else: \n",
    "            self.counter += 1\n",
    "            \n",
    "    @property\n",
    "    def early_stop(self):\n",
    "        return self.counter >= self.patience\n"
   ],
   "outputs": [],
   "execution_count": 14
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T12:57:28.712672Z",
     "start_time": "2025-01-20T12:13:28.979429Z"
    }
   },
   "source": [
    "# 训练\n",
    "def training(\n",
    "    model, \n",
    "    train_loader, \n",
    "    val_loader, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=None,\n",
    "    early_stop_callback=None,\n",
    "    eval_step=500,\n",
    "    ):\n",
    "    record_dict = {\n",
    "        \"train\": [],\n",
    "        \"val\": []\n",
    "    }\n",
    "    \n",
    "    global_step = 0\n",
    "    model.train()\n",
    "    with tqdm(total=epoch * len(train_loader)) as pbar:\n",
    "        for epoch_id in range(epoch):\n",
    "            # training\n",
    "            for datas, labels in train_loader:\n",
    "                datas = datas.to(device)\n",
    "                labels = labels.to(device)\n",
    "                # 梯度清空\n",
    "                optimizer.zero_grad()\n",
    "                # 模型前向计算\n",
    "                logits = model(datas)\n",
    "                # 计算损失\n",
    "                loss = loss_fct(logits, labels)\n",
    "                # 梯度回传\n",
    "                loss.backward()\n",
    "                # 调整优化器，包括学习率的变动等\n",
    "                optimizer.step()\n",
    "                preds = logits.argmax(axis=-1)\n",
    "            \n",
    "                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())    \n",
    "                loss = loss.cpu().item()\n",
    "                # record\n",
    "                \n",
    "                record_dict[\"train\"].append({\n",
    "                    \"loss\": loss, \"acc\": acc, \"step\": global_step\n",
    "                })\n",
    "                \n",
    "                # evaluating\n",
    "                if global_step % eval_step == 0:\n",
    "                    model.eval()\n",
    "                    val_loss, val_acc = evaluating(model, val_loader, loss_fct)\n",
    "                    record_dict[\"val\"].append({\n",
    "                        \"loss\": val_loss, \"acc\": val_acc, \"step\": global_step\n",
    "                    })\n",
    "                    model.train()\n",
    "                    \n",
    "                    # 1. 使用 tensorboard 可视化\n",
    "                    if tensorboard_callback is not None:\n",
    "                        tensorboard_callback(\n",
    "                            global_step, \n",
    "                            loss=loss, val_loss=val_loss,\n",
    "                            acc=acc, val_acc=val_acc,\n",
    "                            lr=optimizer.param_groups[0][\"lr\"],\n",
    "                            )\n",
    "                    \n",
    "                    # 2. 保存模型权重 save model checkpoint\n",
    "                    if save_ckpt_callback is not None:\n",
    "                        save_ckpt_callback(global_step, model.state_dict(), metric=val_acc)\n",
    "\n",
    "                    # 3. 早停 Early Stop\n",
    "                    if early_stop_callback is not None:\n",
    "                        early_stop_callback(val_acc)\n",
    "                        if early_stop_callback.early_stop:\n",
    "                            print(f\"Early stop at epoch {epoch_id} / global_step {global_step}\")\n",
    "                            return record_dict\n",
    "                    \n",
    "                # udate step\n",
    "                global_step += 1\n",
    "                pbar.update(1)\n",
    "                pbar.set_postfix({\"epoch\": epoch_id})\n",
    "        \n",
    "    return record_dict\n",
    "        \n",
    "\n",
    "epoch = 20\n",
    "\n",
    "activation = \"selu\"\n",
    "model = CNN(activation)\n",
    "\n",
    "# 1. 定义损失函数 采用交叉熵损失\n",
    "loss_fct = nn.CrossEntropyLoss()\n",
    "# 2. 定义优化器 采用SGD\n",
    "# Optimizers specified in the torch.optim package\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n",
    "\n",
    "# 1. tensorboard 可视化\n",
    "if not os.path.exists(\"runs\"):\n",
    "    os.mkdir(\"runs\")\n",
    "tensorboard_callback = TensorBoardCallback(f\"runs/dsc-{activation}\")\n",
    "tensorboard_callback.draw_model(model, [1, 1, 28, 28])\n",
    "# 2. save best\n",
    "if not os.path.exists(\"checkpoints\"):\n",
    "    os.makedirs(\"checkpoints\")\n",
    "save_ckpt_callback = SaveCheckpointsCallback(f\"checkpoints/dsc-{activation}\", save_step=len(train_loader), save_best_only=True)\n",
    "# 3. early stop\n",
    "early_stop_callback = EarlyStopCallback(patience=10)\n",
    "\n",
    "model = model.to(device)\n",
    "record = training(\n",
    "    model, \n",
    "    train_loader, \n",
    "    val_loader, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=save_ckpt_callback,\n",
    "    early_stop_callback=early_stop_callback,\n",
    "    eval_step=len(train_loader)\n",
    "    )"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "  0%|          | 0/34380 [00:00<?, ?it/s]"
      ],
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "21a88e570a95469d80a4ce25d4e20aba"
      }
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 15
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T13:02:20.983905Z",
     "start_time": "2025-01-20T13:02:20.781777Z"
    }
   },
   "source": [
    "#画线要注意的是损失是不一定在零到1之间的\n",
    "def plot_learning_curves(record_dict, sample_step=500):\n",
    "    # build DataFrame\n",
    "    train_df = pd.DataFrame(record_dict[\"train\"]).set_index(\"step\").iloc[::sample_step]\n",
    "    val_df = pd.DataFrame(record_dict[\"val\"]).set_index(\"step\")\n",
    "\n",
    "    # plot\n",
    "    fig_num = len(train_df.columns)\n",
    "    fig, axs = plt.subplots(1, fig_num, figsize=(5 * fig_num, 5))\n",
    "    for idx, item in enumerate(train_df.columns):    \n",
    "        axs[idx].plot(train_df.index, train_df[item], label=f\"train_{item}\")\n",
    "        axs[idx].plot(val_df.index, val_df[item], label=f\"val_{item}\")\n",
    "        axs[idx].grid()\n",
    "        axs[idx].legend()\n",
    "        axs[idx].set_xticks(range(0, train_df.index[-1], 5000))\n",
    "        axs[idx].set_xticklabels(map(lambda x: f\"{int(x/1000)}k\", range(0, train_df.index[-1], 5000)))\n",
    "        axs[idx].set_xlabel(\"step\")\n",
    "    \n",
    "    plt.show()\n",
    "\n",
    "plot_learning_curves(record, sample_step=500)  #横坐标是 steps"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ],
      "image/png": "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q1u3boHHnIhd9ezZ03rooYfy/R23xG674oorrDfeeMNT5x3OoW0qW7RLzsSuaJucu77TLoXmmxmdtLQ007PV6WhbxYoVzf01a9bkOFavJQ8++KC8++67snr1ajP95zSdQtdp66ZNm8rw4cMlKSkpzzFujDu33bt3y6FDh3K8DtHR0SZVI/froM6fPy9DhgwxucX6nBo2bChuyF3VaewWLVrIfffdJ8ePHw95nJOxnzp1ynytWbOm+arvfR2NCj7vmmKiMYU675qXe/3110tWVpYZyapRo4Zjsdvef/99iYmJkTZt2sjEiRMlNTU15O87GXtmZqbMmTPHjPhpqoCXzjucQdvkPNqlskPbVPax0y4VrJL4xLFjx8yLXadOnRyP6/3t27cH7mdkZMiIESNk8+bNZgo+Pj5enKYX27fffttcwHRadMqUKXLttdfKt99+a3JH3Rp3KNqYqFCvg/0z25kzZ+Smm24yF+bly5ebhsdpmh6g07tNmjSRXbt2yeOPPy433HCDuTiEhYW5Ina9GD388MPSvXt3c+FVem4jIiLyXKBCnXe9P3ToUElISJBZs2aZ33MydnX77bdLo0aNzAeqrVu3yoQJE0yu9IIFC1wR+zfffGMaEE1z0XznhQsXSuvWrc2HCS+cdziHtsl5tEtlg7apbGOnXSpnHZ3C0rzFypUrm5xM7aG7gV6wbDoSpo2L/mF98MEHMnr0aNfGfbmGDRtm8kw///xzszjUDX73u98Fvm/btq15PZo1a2ZG03r37u2K2DWnWD9oFDdXXkduOnXqZNYNBDeSTsZ+77335jjvumBYz7c26nr+nY5dP+hp46EjfvPnz5eRI0eavGevnHe4nxuv8eWxbaJdKj7aprKNnXapcHyTuqYXWH2RcleV0PtxcXE5XtSffvpJPvvsM3Er7YVfeeWVsnPnTk/FrexzfanXQd14441mhCTUVKpbaLqGvreCXwsnYx83bpx8/PHHZrROGzSbnltNkcldKjLUedcRP63ys23bNnFD7KHoByqV+7w7FbuOcjVv3lwSExNNpR5dODxjxgxPnHc4i7bJebRLpY+2qexjp10qZx0dfcH1xV62bFmOqUi9r1N7tltuucVMz91zzz0mp9GNdPpZRwt05MBLcSudWtc/pODXITk52VS5CX4dlOYZa9UQfW5FHYUoK/v37ze50MGvhROx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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 18
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 评估"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T13:02:32.236468Z",
     "start_time": "2025-01-20T13:02:24.918777Z"
    }
   },
   "source": [
    "# dataload for evaluating\n",
    "\n",
    "# load checkpoints\n",
    "model.load_state_dict(torch.load(f\"checkpoints/dsc-{activation}/best.ckpt\", weights_only=True,map_location=\"cpu\"))\n",
    "\n",
    "model.eval()\n",
    "loss, acc = evaluating(model, test_loader, loss_fct)\n",
    "print(f\"loss:     {loss:.4f}\\naccuracy: {acc:.4f}\")"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loss:     0.3740\n",
      "accuracy: 0.8624\n"
     ]
    }
   ],
   "execution_count": 19
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pytorch",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.8"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
